﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2022 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

namespace Abc.Base;

public static class WebExtensions
{
    /// <summary>
    /// 获取当前域名(http://xxx.com)
    /// </summary>
    /// <param name="httpContext">当前http上下文</param>
    /// <returns></returns>
    public static string GetDomain(this HttpContext httpContext)
    {
        return new StringBuilder()
.Append(httpContext.Request.Scheme)
.Append("://")
.Append(httpContext.Request.Host).ToString();
    }

    /// <summary>
    /// 获取不包含Host的url部分(/home/index?abc=12312)
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static string GetUrlNoHost(this HttpContext httpContext)
    {
        return new StringBuilder()
                    //.Append(request.Scheme)
                    //.Append("://")
                    //.Append(request.Host)
                    .Append(httpContext.Request.PathBase)
                    .Append(httpContext.Request.Path)
                    .Append(httpContext.Request.QueryString)
                    .ToString();
    }

    /// <summary>
    /// 获取不包含Host的url部分(http://xxx.com/home/index?abc=12312)
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static string GetUrl(this HttpContext httpContext)
    {
        return new StringBuilder()
                    .Append(httpContext.Request.Scheme)
                    .Append("://")
                    .Append(httpContext.Request.Host)
                    .Append(httpContext.Request.PathBase)
                    .Append(httpContext.Request.Path)
                    .Append(httpContext.Request.QueryString)
                    .ToString();
    }

    /// <summary>
    /// 设置通过appsettings 可以下载文件类型 扩展
    /// 此扩展需要在  app.UseStaticFiles() 之前使用
    /// </summary>
    /// <param name="app"></param>
    public static void UseCustomStaticFile(this IApplicationBuilder app)
    {
        var mimes = App.GetConfig<Dictionary<string, string>>("StaticFileOptions:FileExtensionContentType");
        var serveUnknownFileTypes = App.GetConfig<bool>("StaticFileOptions:ServeUnknownFileTypes");
        var physicalFilePath = App.GetConfig<string>("StaticFileOptions:PhysicalFilePath");

        //var a = new PhysicalFileProvider(Directory.GetCurrentDirectory()); ;

        var options = new StaticFileOptions
        {
            //FileProvider = new PhysicalFileProvider(Directory.GetCurrentDirectory()),
            //设置不限制content-type 该设置可以下载所有类型的文件，但是不建议这么设置，因为不安全
            //ServeUnknownFileTypes = true
            //下面设置可以下载apk和nupkg类型的文件
            //ContentTypeProvider = new FileExtensionContentTypeProvider(new Dictionary<string, string>
            //{
            //  { ".apk","application/vnd.android.package-archive"},
            //  //{ ".nupkg","application/zip"}
            //})
            ServeUnknownFileTypes = serveUnknownFileTypes,
        };
        if (mimes != null && mimes.Any())
        {
            options.ContentTypeProvider = new FileExtensionContentTypeProvider(mimes);
        }
        if (!string.IsNullOrWhiteSpace(physicalFilePath) && Directory.Exists(physicalFilePath))
        {
            options.FileProvider = new PhysicalFileProvider(physicalFilePath);
        }
        app.UseStaticFiles(options);
        app.UseStaticFiles();//可重复设置，设置后不会异常
    }

    /// <summary>
    /// 获取访问信息
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static string GetWebVisitInfo(this HttpContext httpContext)
    {
        if (httpContext == null) return "";
        var logcontent = new StringBuilder();
        logcontent.AppendLine($"  访问地址： {httpContext.Request.Path}{httpContext.Request.QueryString}");
        var ipv4 = httpContext.GetRemoteIpAddressToIPv4();
        var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
        logcontent.AppendLine($"IPV4: {ipv4}    IPV6: {ipv6}");

        var headers = httpContext.Request.Headers.ToDictionary(x => x.Key, v => v.Value.ToString());
        logcontent.AppendLine($"Header：{headers.ToJson()}");

        //var area = context.RouteData.Values["area"]?.ToString() ?? "";
        //var controller = context.RouteData.Values["controller"]?.ToString() ?? "";
        //var action = actionContext.RouteData.Values["action"]?.ToString() ?? "";
        // method ：OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
        try
        {
            if (httpContext.Request.Method.ToLower() != "get")
            {
                if (httpContext.Request.HasFormContentType)
                {
                    var form = httpContext.Request.Form;
                    logcontent.AppendLine($"Form 参数：{form.ToDictionary(x => x.Key, v => v.Value.ToString()).ToJson()}");
                }
                else
                {
                }
            }
        }
        catch (Exception ex)
        {
            var _logger = AppEx.GetLogger("WebActionFilter");
            _logger.Error(ex.ToStringEx());
        }
        //URL  参数
        if (httpContext.Request.Query.Any())
        {
            var urlpars = httpContext.Request.Query.ToDictionary(x => x.Key, v => v.Value.ToString());
            logcontent.AppendLine($"URL 参数：{urlpars.ToJson()}");
        }

        return logcontent.ToString();
    }

    ///// <summary>
    ///// 获取访问信息
    ///// </summary>
    ///// <param name="httpContext"></param>
    ///// <returns></returns>
    //public static void GetWebVisitInfo(this ActionExecutingContext context, LogVisitEntity logVisitEntity)
    //{
    //    if (context == null) return;
    //    if (logVisitEntity == null) logVisitEntity = new();

    //    context.HttpContext.GetWebVisitInfo(logVisitEntity);
    //    //logVisitEntity.Area = context.RouteData.Values["area"]?.ToString() ?? "";
    //    //logVisitEntity.Controller = context.RouteData.Values["controller"]?.ToString() ?? "";
    //    //logVisitEntity.Action = context.RouteData.Values["action"]?.ToString() ?? "";
    //}

    ///// <summary>
    ///// 获取访问信息
    ///// </summary>
    ///// <param name="httpContext"></param>
    ///// <returns></returns>
    //public static void GetWebVisitInfo(this HttpContext httpContext, LogVisitEntity logVisitEntity)
    //{
    //    if (httpContext == null) return;

    //    // var rdata = new LogVisitEntity();
    //    logVisitEntity.RemoteAddr = $"IPV4: {httpContext.GetRemoteIpAddressToIPv4()}\r\n IPV6: {httpContext.GetRemoteIpAddressToIPv6()}";//IPV4+IPV6

    //    logVisitEntity.IPv4 = httpContext.GetRemoteIpAddressToIPv4();
    //    logVisitEntity.IPv6 = httpContext.GetRemoteIpAddressToIPv6();

    //    logVisitEntity.RequestUrl = httpContext.GetDomain();
    //    logVisitEntity.Method = $"{httpContext.Request.Path}{httpContext.Request.QueryString}";

    //    logVisitEntity.Area = httpContext.Request.RouteValues["area"]?.ToString() ?? "";
    //    logVisitEntity.Controller = httpContext.Request.RouteValues["controller"]?.ToString() ?? "";
    //    logVisitEntity.Action = httpContext.Request.RouteValues["action"]?.ToString() ?? "";

    //    if (!string.IsNullOrWhiteSpace(logVisitEntity.Area))
    //    {
    //        logVisitEntity.RequestUrl = $"{logVisitEntity.RequestUrl}/{logVisitEntity.Area}";
    //    }
    //    if (!string.IsNullOrWhiteSpace(logVisitEntity.Controller))
    //    {
    //        logVisitEntity.RequestUrl = $"{logVisitEntity.RequestUrl}/{logVisitEntity.Controller}";
    //    }
    //    if (!string.IsNullOrWhiteSpace(logVisitEntity.Action))
    //    {
    //        logVisitEntity.RequestUrl = $"{logVisitEntity.RequestUrl}/{logVisitEntity.Action}";
    //    }

    //    //var logcontent = $"访问地址：{httpContext.Request.Path}{httpContext.Request.QueryString}";
    //    //var ipv4 = httpContext.GetRemoteIpAddressToIPv4();
    //    //var ipv6 = httpContext.GetRemoteIpAddressToIPv6();
    //    //logcontent += $"IPV4:{ipv4}    IPV6:{ipv6}";

    //    //var headers = httpContext.Request.Headers.ToDictionary(x => x.Key, v => v.Value.ToString());
    //    //logcontent += $"Header：{System.Text.Json.JsonSerializer.Serialize(headers, AppEx.GetDefaultJsonSerializerOptions)}";
    //    logVisitEntity.Header = httpContext?.Request?.Headers?.ToDictionary(x => x.Key, v => v.Value.ToString())?.ToJson() ?? "";

    //    var par = "";

    //    // method ：OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法
    //    try
    //    {
    //        if (httpContext.Request.Method.ToLower() != "get")
    //        {
    //            var form = httpContext.Request.Form;
    //            //Form 参数：
    //            logVisitEntity.Params = $"{System.Text.Json.JsonSerializer.Serialize(form.ToDictionary(x => x.Key, v => v.Value.ToString()), AppEx.GetDefaultJsonSerializerOptions)}";
    //        }
    //    }
    //    catch (Exception ex)
    //    {
    //        AppEx.GetLogger(logFloderName: "WebActionFilter").Error(ex.ToStringEx());
    //    }
    //    //URL  参数
    //    if (httpContext.Request.Query.Any())
    //    {
    //        var urlpars = httpContext.Request.Query.ToDictionary(x => x.Key, v => v.Value.ToString());
    //        //URL 参数：
    //        logVisitEntity.UrlParams = $"{System.Text.Json.JsonSerializer.Serialize(urlpars, AppEx.GetDefaultJsonSerializerOptions)}";
    //    }

    //    //浏览器信息
    //    //#if NET5
    //    //            var useragent = httpContext?.Request?.Headers["User-Agent"].To<string>();
    //    //#elif NET6
    //    var useragent = httpContext?.Request?.Headers?.UserAgent.ToString();

    //    //#endif
    //    if (!string.IsNullOrWhiteSpace(useragent))
    //    {
    //        // var s = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36";
    //        // 获取具有嵌入正则表达式模式的解析器
    //        var uaParser = Parser.GetDefault();

    //        // get a parser using externally supplied yaml definitions
    //        // var uaParser = Parser.FromYaml(yamlString);
    //        //使用外部提供的yaml定义获取解析器
    //        UAParser.ClientInfo c = uaParser.Parse(useragent);
    //        logVisitEntity.Os = c.OS.ToString();
    //        logVisitEntity.Device = c.Device.ToString();
    //        logVisitEntity.Browser = c.UA.Family;
    //    }

    //    // return rdata;
    //}

    /// <summary>
    /// 获取IPV4
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static string GetIpV4(this HttpContext httpContext)
    {
        return httpContext.GetRemoteIpAddressToIPv4();
    }

    /// <summary>
    /// 获取IPV4
    /// </summary>
    /// <param name="httpContextAccessor"></param>
    /// <returns></returns>
    public static string GetIpV4(this IHttpContextAccessor httpContextAccessor)
    {
        return httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4();
    }

    /// <summary>
    /// 获取IPV6
    /// </summary>
    /// <param name="httpContext"></param>
    /// <returns></returns>
    public static string GetIpV6(this HttpContext httpContext)
    {
        return httpContext.GetRemoteIpAddressToIPv6();
    }

    /// <summary>
    /// 获取IPV6
    /// </summary>
    /// <param name="httpContextAccessor"></param>
    /// <returns></returns>
    public static string GetIpV6(this IHttpContextAccessor httpContextAccessor)
    {
        return httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv6();
    }

    /// <summary>
    /// 获取文件
    /// </summary>
    /// <param name="logicalPath">逻辑路径（假路径，不是真的，防止从url直接访问到文件）</param>
    /// <returns></returns>
    //[Route("/u/f/{name?}/{name2?}/{name3?}/{name4?}/{name5?}/{name6?}/{name7?}/{name8?}/{name9?}/{name10?}")]
    //[UploadFileFilter]
    public static IActionResult GetFile(this Controller controller, string defaultPhysicalPath, string logicalPath = "/u/f", string baseFloder = "upload")  //要下载文件码
    {
        var httpContext = App.HttpContext;

        ////图片防盗链 验证（基础认证，能防御基础的爬虫手段）
        ////var applicationUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host.Value}";
        //var headersDictionary = httpContext.Request.Headers;
        //var urlReferrer = headersDictionary[HeaderNames.Referer].ToString()??"";

        //var domain = httpContext.GetDomain();

        //if (!string.IsNullOrEmpty(urlReferrer) && !urlReferrer.StartsWith(domain))
        //{
        //   //返回默认图片，提示
        //}

        var pathurl = Path.Combine(httpContext.Request.Path, httpContext.Request.QueryString.Value ?? "");
        //默认物理文件夹
        //var defaultPhysicalPath = App.Configuration["AppInfo:WebUploadFloder"];
        if (string.IsNullOrWhiteSpace(defaultPhysicalPath) || !Directory.Exists(defaultPhysicalPath))
        {
            //如果不存在，设置默认的物理文件，网站更目录下
            defaultPhysicalPath = AppEx.GetUploadDefaultFloder();
        }
        var filepath = Path.Combine(defaultPhysicalPath, baseFloder, $"{pathurl.TrimStart(logicalPath)}");

        if (!System.IO.File.Exists(filepath)) return controller.Content("");
        var stream = System.IO.File.OpenRead(filepath);  //创建文件流
        return controller.File(stream, filepath.GetFileMimeType());
    }

    /// <summary>
    /// 获取文件
    /// </summary>
    /// <param name="relativePath">逻辑路径（假路径，不是真的，防止从url直接访问到文件）</param>
    /// <returns></returns>
    //[Route("/u/f/{name?}/{name2?}/{name3?}/{name4?}/{name5?}/{name6?}/{name7?}/{name8?}/{name9?}/{name10?}")]
    //[UploadFileFilter]
    public static IActionResult GetDbFile(this Controller controller, string defaultPhysicalPath, string relativePath)  //要下载文件码
    {
        //var httpContext = App.HttpContext;

        ////图片防盗链 验证（基础认证，能防御基础的爬虫手段）
        ////var applicationUrl = $"{httpContext.Request.Scheme}://{httpContext.Request.Host.Value}";
        //var headersDictionary = httpContext.Request.Headers;
        //var urlReferrer = headersDictionary[HeaderNames.Referer].ToString()??"";

        //var domain = httpContext.GetDomain();

        //if (!string.IsNullOrEmpty(urlReferrer) && !urlReferrer.StartsWith(domain))
        //{
        //   //返回默认图片，提示
        //}

        //var pathurl = Path.Combine(httpContext.Request.Path, httpContext.Request.QueryString.Value ?? "");
        //默认物理文件夹
        //var defaultPhysicalPath = App.Configuration["AppInfo:WebUploadFloder"];
        if (string.IsNullOrWhiteSpace(defaultPhysicalPath) || !Directory.Exists(defaultPhysicalPath))
        {
            //如果不存在，设置默认的物理文件，网站更目录下
            defaultPhysicalPath = AppEx.GetUploadDefaultFloder();
        }
        var filepath = Path.Combine(defaultPhysicalPath, "upload", $"{relativePath.TrimStart('/').TrimStart('\\')}");

        if (!System.IO.File.Exists(filepath)) return controller.Content("");
        var stream = System.IO.File.OpenRead(filepath);  //创建文件流
        return controller.File(stream, filepath.GetFileMimeType());
    }
}